package progress.exa8;

import java.util.ArrayList;

/**
 * 泛型类学习
 */
public class GenericClass {

    public static void main(String[] args) {
        //useGenericClass();
        useNoGenericClass();
    }

    /**
     * 此方法展示了如何使用泛型类
     */
    public static void useGenericClass() {
        GenericStack<Integer> stack = new GenericStack<>();
        stack.push(12);
        System.out.println(stack.peek());
    }

    /**
     * 此方法展示不使用泛型所带来的风险
     * 下面代码编译时不会报错，但是运行时会爆出ClassCastException错误
     */
    public static void useNoGenericClass() {
        GenericStack1 stack1 = new GenericStack1();
        stack1.push(11);
        System.out.println((String)stack1.pop());
    }

}

/**
 * 泛型： 泛指类型，是所有类型的统称
 * 泛型类：带有泛型参数的类
 * 下面定义了泛型栈数据结构
 * @param <E>
 */
class GenericStack<E> {

    //定义一个链表，链表中存储的元素设定为泛型E
    private final ArrayList<E> list = new ArrayList<>();

    public int getSize() {
        return list.size();
    }

    /**
     * 此方法返回泛型E
     * @return
     */
    public E peek(){
        return list.get(getSize()-1);
    }

    /**
     * 此方法将类型为E的元素存入
     * @param o
     */
    public void push(E o) {
        list.add(o);
    }

    public E pop(){
        E o = list.get(getSize()-1);
        list.remove(getSize()-1);
        return o;
    }

    public boolean isEmpty(){
        return list.isEmpty();
    }
}


/**
 * 这个类和上面的类形成对比，此类的定义没有使用泛型机制
 * 所以导致客户代码在调用时存在运行时异常风险
 */
class GenericStack1{
    //定义一个链表，链表中存储的元素设定为E
    private ArrayList list=new ArrayList();

    public int getSize() {
        return list.size();
    }

    public Object peek(){
        return list.get(getSize()-1);
    }

    public void push(Object o) {
        list.add(o);
    }

    public Object pop(){
        Object o = list.get(getSize()-1);
        list.remove(getSize()-1);
        return o;
    }

    public boolean isEmpty(){
        return list.isEmpty();
    }
}